#pragma onec
#include <iostream>
#include <time.h>
#include <cstdarg>
#include <cstdio>
#include <unistd.h>
#include <fcntl.h>
#include <cstring>
#include <sys/types.h>
#include <sys/stat.h>
#define SIZE 1024
enum{
    INFO = 1,
    WARNING,
    ERROR,
    FATAL,
    DEBUG
};

enum{
    SCREEN = 1,
    ONEFILE,
    MANYFILE
};

class Log
{
    
public:

    Log()
    {
        _printfway = SCREEN;
        _local = "./log";
    }

    void printfway(int way)
    {
        _printfway = way;
    }


    const char* GetGrade(int level)
    {
        switch(level)
        {
            case INFO:
                return "info";
            case WARNING:
                return "warning";
            case ERROR:
                return "error";
            case FATAL:
                return "fafal";
            case DEBUG:
                return "debug";
        }
    }

    void operator()(int level,const char * format,...)
    {
        
        time_t t = time(nullptr);
        struct tm* tm = localtime(&t);
        char timestr[SIZE];
        snprintf(timestr,sizeof(timestr),"[%s][%d-%d-%d %d:%d:%d]",GetGrade(level),tm->tm_year + 1900,tm->tm_mon + 1,
        tm->tm_mday,tm->tm_hour,tm->tm_min,tm->tm_sec);
        
        va_list s;
        va_start(s,format);
        char gradestr[SIZE];
        vsnprintf(gradestr,sizeof(gradestr),format,s);
        va_end(s);

        char logstr[SIZE*2];
        snprintf(logstr,sizeof(logstr),"%s[%s]",timestr,gradestr);

       Printflog(level,logstr);
    }

    void Printflog(int level,char * logstr)
    {
        switch(_printfway)
        {
            case SCREEN:
            {
                std::cout<<logstr<<std::endl;
                break;
            }
            case ONEFILE:
            {
                onefile(logstr);
                break;
            }
            case MANYFILE:
            {
                manyfile(level,logstr);
                break;
            }
            default:
                break;
                
        }
    }

    void onefile(char * logstr)
    {
        int fd = open(_local,O_CREAT | O_WRONLY | O_APPEND,0664);
        if(fd == -1)
        {
            perror("open");
        }

        write(fd,logstr,strlen(logstr) + 1);
        close(fd);
    }

    void manyfile(int level,char * logstr)
    {
        char tmp[SIZE*2];
        snprintf(tmp,sizeof(tmp),"%s.%s",_local,GetGrade(level));

        onefile(tmp);
    }

private:
    int _printfway;
    const char* _local;

};